# -*- coding:utf-8 -*-
import sys
import collections.abc
import os
from tempfile import TemporaryDirectory
from src.utils.runcmd import read_file, rpm_setup, cp_catalog, \
    cp_file, exec_with_redirect
from src.utils.logger import logger

class TmplateParser(object):
    def __init__(self, file_path):
        self._tmpl_file_path = file_path
        logger.info("tmpl file is %s", self._tmpl_file_path)

    def parse(self):
        # read file

        textbuf = read_file(self._tmpl_file_path)
        lines = textbuf.splitlines()
        lines = [line.strip() for line in lines]
        # remove empty lines
        lines = [line for line in lines if line]

        # remove comments
        lines = [line for line in lines if not line.startswith("#")]
        expanded_lines = []
        for line in lines:
            expanded_lines.append(line.split(" "))
        return expanded_lines


class TmplateRunner(object):
    def __init__(self, file_path):
        self._file_path = file_path

    def run(self):
        parser = TmplateParser(self._file_path)
        commands = parser.parse()
        self._run(commands)

    def _run(self, parsed_template):
        logger.info("running template %s", self._file_path)
        for (num, line) in enumerate(parsed_template, 1):
            logger.debug("template line %i: %s", num, " ".join(line))
            (cmd, args) = (line[0], line[1:])
            try:
                f = getattr(self, cmd, None)
                if not isinstance(f, collections.abc.Callable):
                    raise ValueError("unknown command %s" % cmd)
                f(*args)
            except:
                logger.error("template command error in %s:", self._file_path)
                logger.error("  %s", " ".join(line))
                sys.exit(0)


class OerebuildTmplateRunner(TmplateRunner):
    def __init__(self, file_path, src, dest):
        """

        :param file_path: tmpl file path
        :param src: new rpms path
        :param dest: temp dir path
        """
        super().__init__(file_path)
        self._dest = dest
        self._src = src

    def installpkg(self, pkg):
        """
        installpkg PKG
          install pkg to mini iso

        Examples:
          installpkg openEuler-release /tmp/install
        :param pkg: pkg path
        """
        pkg_path = os.path.join(self._src, pkg)
        if rpm_setup(pkg_path, self._dest) != 0:
            raise

    def installfile(self, *args):
        """
        installfile PKG SRC
        :param pkg: pkg path
        :param src: src path
        """
        package_prefix = "package_"
        pkg = args[0]
        with TemporaryDirectory(prefix=package_prefix, dir="/var/tmp") as tmpdir:
            pkg_path = os.path.join(self._src, pkg)
            if rpm_setup(pkg_path, tmpdir) != 0:
                sys.exit(0)
            for src in args[1:]:
                src_path = os.path.join(tmpdir, "./" + src)
                if os.path.exists(src_path) is False:
                    logger.error("can not found file %s", src)
                    raise
                dest_path = os.path.join(self._dest, "." + src)
                if os.path.isdir(src_path):
                    if cp_catalog(src_path, dest_path) != 0:
                        raise
                else:
                    cp_file(src_path, dest_path)

    def runcmd(self, *args):
        """
        runcmd cmd
        :param args:cmd line
        """
        ret = exec_with_redirect(args, root=self._dest)
        if ret[0] != 0:
            logger.error(ret[1])
            raise

